package org.yumeko.cmdb.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.yumeko.cmdb.entiy.InstanceData;
import org.yumeko.cmdb.entiy.ServiceData;
import org.yumeko.cmdb.entiy.UserData;
import org.yumeko.cmdb.util.CmdbProperties;
import org.yumeko.cmdb.util.CmdbUtil;

import java.util.*;

@Service
@Slf4j
public class CmdbServiceImpl {


    private final CmdbProperties cmdbProperties;
    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;

    // redis分布式锁
    //。。。。。。。。。。。。。。。。。

    @Autowired
    public CmdbServiceImpl(CmdbProperties cmdbProperties, RestTemplate restTemplate, ObjectMapper objectMapper) {
        this.cmdbProperties = cmdbProperties;
        this.restTemplate = restTemplate;
        this.objectMapper = objectMapper;
    }

    /**
     * 定时任务，每3分钟执行一次
     */
    @Scheduled(fixedRate = 60000) // 每10分钟执行一次
//    @Scheduled(cron = "0 0 0 * * FRI") // 每周五凌晨0点执行
//    @Scheduled(cron = "0 0 0 * * ?")
    public void fetchAllModel() {
        log.info("开始CMDB数据采集---------------");
        for (String modelName : cmdbProperties.getModelNames()) {
            fetchDataForModel(modelName);
        }
        log.info("结束CMDB数据采集---------------");
    }
    /**
     * 调用cmdb接口，获取数据
     * @param modelName
     */
    private void fetchDataForModel(String modelName) {
        log.info("--------开始获取模型的实例: {}--------", modelName);
        int page = 1;
        boolean hasMoreData = true;
        while (hasMoreData) {
            String url = cmdbProperties.getHost() + "/api/v6/cmdb/instances";
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            // 生成请求参数
            Map<String, Object> params = CmdbUtil.generateParams(cmdbProperties, modelName,page);
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(params, headers);
            ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);
            if (response.getStatusCode() == HttpStatus.OK) {
                String responseBody = response.getBody();
                try {
                    Map<String, Object> insts = objectMapper.readValue(responseBody, Map.class);
                    if ((int) insts.get("code") != 0) {
                        hasMoreData = false;
                        log.error("查询失败，错误信息：{}", insts.get("message"));
                    } else {
                        // 检查 data 节点中的 rows 是否存在且不为空
                        JsonNode dataNode = objectMapper.readTree(responseBody).get("data");
                        JsonNode rowsNode = dataNode.get("rows");
                        if (rowsNode.size() > 0) {
                            processData(rowsNode,modelName);
                            page++;
                        } else {
                            log.info("--------当前模型:{}数据查询结束--------",modelName);
                            hasMoreData = false;
                        }
                    }
                } catch (Exception e) {
                    hasMoreData = false;
                    log.error("请求异常: {}", e.getMessage(), e);
                }
            } else {
                hasMoreData = false;
                log.error("请求失败，状态码：{}", response.getStatusCode());
            }
        }
        log.info("--------结束获取模型的实例: {}---------", modelName);
    }
    /**
     * 执行不同实例
     * @param dataRows
     * @param modelName
     */
    private void processData(JsonNode dataRows,String modelName) {
        Optional.ofNullable(modelName)
                .map(String::trim)
                .map(name -> name.toLowerCase())
                .map(name -> name.contains("_") ? name.substring(name.lastIndexOf('_') + 1) : name)
                .ifPresent(name -> {
                    switch (name) {
                        case "instance":
                            insertIntoInstance(dataRows, modelName);
                            break;
                        case "service":
                            insertIntoService(dataRows, modelName);
                            break;
                        case "user":
                            insertIntoUser(dataRows, modelName);
                            break;
                        default:
                            log.warn("未知的 modelName: {}", name);
                            break;
                    }
                });
    }
    /**
     * mybatis 批量插入*_instance数据
     * @param dataRows
     * @param modelName
     */
    private void insertIntoInstance(JsonNode dataRows, String modelName) {
        log.info("..........开始处理 {} 数据..........:",modelName);
        for (JsonNode row : dataRows) {
            String id = row.get("id").asText();
            String modelId = row.get("model_id").asText();
            JsonNode data = row.get("data");
            String systemId = data.get("系统内置ID").asText();
            String monitor = data.get("是否监控").asText();
            String serviceName = data.get("service_name").asText();
            String clusterName = data.get("cluster_name").asText();
//            String cnName = data.get("cn_name").asText();
            String hostName = data.get("host_name").asText();
            String ipAddress = data.get("ip_address").asText();
//            String instancePort = data.get("instance_port").asText();
//            String accessPort = data.get("access_port").asText();
            String dataCenter = data.get("data_center").asText();
            String privateNetwork = data.get("private_network").asText();
            String securityDomain = data.get("security_domain").asText();
            String isSelfOperation = data.get("is_self_operation").asText();
            String instancePort;
            if ("oracle_instance".equals(modelName)) {
                instancePort = data.get("port").asText();
            }else {
                instancePort = data.get("instance_port").asText();
            }
            InstanceData instanceData = new InstanceData();
            instanceData.setId(id);
            instanceData.setModelId(modelId);
            instanceData.setModelName(modelName);
            instanceData.setSystemId(systemId);
            instanceData.setMonitor(Boolean.parseBoolean(monitor));
            instanceData.setServiceName(serviceName);
            instanceData.setClusterName(clusterName);
//            instanceData.setCnName(cnName);
            instanceData.setHostName(hostName);
            instanceData.setIpAddress(ipAddress);
            instanceData.setInstancePort(Integer.parseInt(instancePort));
//            instanceData.setAccessPort(Integer.parseInt(accessPort));
            instanceData.setDataCenter(dataCenter);
            instanceData.setPrivateNetwork(privateNetwork);
            instanceData.setSecurityDomain(securityDomain);
            instanceData.setIsSelfOperation(Boolean.parseBoolean(isSelfOperation));
        }
        log.info("..........结束处理 {} 数据..........:",modelName);
    }
    /**
     * mybatis 批量插入*_service数据
     * @param dataRows
     * @param modelName
     */
    private void insertIntoService(JsonNode dataRows, String modelName) {
        log.info("..........开始处理 {} 数据..........:",modelName);
        for (JsonNode row : dataRows) {
            String id = row.get("id").asText();
            String modelId = row.get("model_id").asText();
            JsonNode data = row.get("data");
            String systemId = data.get("系统内置ID").asText();
            String monitor = data.get("是否监控").asText();
            String serviceName = data.get("service_name").asText();
            String clusterName = data.get("cluster_name").asText();
            String databaseVersion = data.get("database_version").asText();
//            String accessAddress = data.get("access_address").asText();
//            String accessDomainName = data.get("access_domain_name").asText();
            String rwAccessAddress = data.get("rw_access_address").asText();
            String roAccessAddress = data.get("ro_access_address").asText();
            String rwAccessDomainName = data.get("rw_access_domain_name").asText();
            String roAccessDomainName = data.get("ro_access_domain_name").asText();
            String operationalArchitecture = data.get("operational_architecture").asText();
            String operatingMode;
            if("otherDB_service".equals(modelName)){
                operatingMode= "";
            }else{
                operatingMode = data.get("operating_mode").asText();
            }
            String instanceNumber = data.get("instance_number").asText();
            String itSystemId = data.get("it_system_id").asText();
            String responsiblePerson = data.get("responsible_person").asText();
            String dataCenter = data.get("data_center").asText();
            String privateNetwork = data.get("private_network").asText();
            String securityDomain = data.get("security_domain").asText();
            String isSelfOperation = data.get("is_self_operation").asText();
//            String serviceUid = data.get("service_uid").asText();
//            String dbcloudUid = data.get("dbcloud_uid").asText();
            ServiceData serviceData = new ServiceData();
            serviceData.setId(id);
            serviceData.setModelId(modelId);
            serviceData.setModelName(modelName);
            serviceData.setSystemId(systemId);
            serviceData.setMonitor(Boolean.parseBoolean(monitor));
            serviceData.setServiceName(serviceName);
            serviceData.setClusterName(clusterName);
            serviceData.setDatabaseVersion(databaseVersion);
//            serviceData.setAccessAddress(accessAddress);
//            serviceData.setAccessDomainName(accessDomainName);
            serviceData.setRwAccessAddress(rwAccessAddress);
            serviceData.setRoAccessAddress(roAccessAddress);
            serviceData.setRwAccessDomainName(rwAccessDomainName);
            serviceData.setRoAccessDomainName(roAccessDomainName);
            serviceData.setOperationalArchitecture(operationalArchitecture);
            serviceData.setOperatingMode(operatingMode);
            serviceData.setInstanceNumber(Integer.parseInt(instanceNumber));
            serviceData.setItSystemId(itSystemId);
            serviceData.setResponsiblePerson(responsiblePerson);
            serviceData.setDataCenter(dataCenter);
            serviceData.setPrivateNetwork(privateNetwork);
            serviceData.setSecurityDomain(securityDomain);
            serviceData.setIsSelfOperation(Boolean.parseBoolean(isSelfOperation));
//            serviceData.setServiceUid(serviceUid);
//            serviceData.setDbcloudUid(dbcloudUid);
            System.out.println("1:"+ serviceData.getRwAccessAddress());
            System.out.println("2:"+ serviceData.getRoAccessAddress());
            System.out.println("3:"+ serviceData.getRwAccessDomainName());
            System.out.println("4:"+ serviceData.getRoAccessDomainName());
            System.out.println("-------------------------------------");
        }
        log.info("..........结束处理 {} 数据..........:",modelName);
    }
    /**
     * mybatis 批量插入*_user数据
     * @param dataRows
     * @param modelName
     */
    private void insertIntoUser(JsonNode dataRows, String modelName) {
        log.info("..........开始处理 {} 数据..........:",modelName);
        for (JsonNode row : dataRows) {
            String id = row.get("id").asText();
            String modelId = row.get("model_id").asText();
            JsonNode data = row.get("data");
            String systemId = data.get("系统内置ID").asText();
            String monitor = data.get("是否监控").asText();
            String serviceName = data.get("service_name").asText();
            String clusterName = data.get("cluster_name").asText();
            String userName = data.get("user_name").asText();
            String userType = data.get("user_type").asText();
            String isSelfOperation = data.get("is_self_operation").asText();
            String accountManager = data.get("account_manager").asText();

            UserData userData = new UserData();
            userData.setId(id);
            userData.setModelId(modelId);
            userData.setModelName(modelName);
            userData.setSystemId(systemId);
            userData.setMonitor(Boolean.parseBoolean(monitor));
            userData.setServiceName(serviceName);
            userData.setClusterName(clusterName);
            userData.setUserName(userName);
            userData.setUserType(userType);
            userData.setIsSelfOperation(Boolean.parseBoolean(isSelfOperation));
            userData.setAccountManager(accountManager);
        }
        log.info("..........结束处理 {} 数据..........:",modelName);
    }
}